home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UCRASM25.ARJ / CPUID.ASM < prev    next >
Assembly Source File  |  1991-10-24  |  6KB  |  202 lines

  1. StdGrp        group    StdLib, StdData
  2. ;
  3. StdData        segment    para public 'sldata'
  4. ;
  5. fp_status    dw    ?
  6. present        dw    0
  7. FPU        dw    0
  8. ;
  9. StdData        ends
  10. ;
  11. ;
  12. ;
  13. ;
  14. StdLib        segment    para public 'slcode'
  15.         assume    cs:StdGrp, ds:StdGrp
  16. ;
  17. ;    The purpose of this code is to allow the user the ability to identify
  18. ;    the processor and coprocessor that is currently in the system.  The
  19. ;    algorithm of the program is to first determine the processor id.
  20. ;    When that is accomplished, the program continues to then identify
  21. ;    whether a coprocessor exists in the system.  If a coprocessor or
  22. ;    integrated coprocessor exists, the program will identify the
  23. ;    coprocessor id.  If one does not exist, the program then terminates.
  24. ;
  25. ;    Returns in AX one of the following values:
  26. ;
  27. ;           86    if 8088 or 8086 microprocessor
  28. ;        286    if 80286 microprocessor
  29. ;        386    if 80386 microprocessor
  30. ;        486    if 80486 microprocessor (or 486sx w/487 coprocessor)
  31. ;
  32. ;    Returns in BX one of the following values:
  33. ;
  34. ;        0    if no numeric coprocessor
  35. ;        87    if 8087 math coprocessor available
  36. ;        287    if 80287 math coprocessor available
  37. ;        387    if 80387 math coprocessor available
  38. ;        487    if 80486dx cpu or 486sx + 487 coprocessor
  39. ;
  40. ;    Originally created by the nice folks at Intel.  Modified for
  41. ;    inclusion in the standard library by rhyde 10/24/91.
  42. ;
  43. ;
  44. ;
  45.         public    sl_cpuid
  46. sl_cpuid    proc    far
  47.         push    ds
  48.         push    cx
  49. ;
  50.         mov    ax, StdGrp
  51.         mov    ds,ax           ; set segment register
  52. ;
  53.         mov    FPU, 0
  54. ;
  55. ;    8086 CPU check
  56. ;    Bits 12-15 are always set on the 8086 processor.
  57. ;
  58.         pushf            ; save EFLAGS
  59.         pop    bx        ; store EFLAGS in BX
  60.         mov    ax,0fffh    ;  clear bits 12-15
  61.         and    ax,bx        ;  in EFLAGS
  62.         push    ax        ; store new EFLAGS value on stack
  63.         popf            ; replace current EFLAGS value
  64.         pushf            ; set new EFLAGS
  65.         pop    ax        ; store new EFLAGS in AX
  66.         and    ax,0f000h    ; if bits 12-15 are set, then CPU
  67.         cmp    ax,0f000h    ;     is an 8086/8088
  68.         mov     present, 86    ; turn on 8086/8088 flag
  69.         je    check_fpu    ; if CPU is 8086/8088, check for 8087
  70.  
  71. ;
  72. ;    80286 CPU check
  73. ;    Bits 12-15 are always clear on the 80286 processor.
  74. ;
  75.  
  76.         or    bx,0f000h    ; try to set bits 12-15
  77.         push     bx
  78.         popf
  79.         pushf
  80.         pop    ax
  81.         and    ax,0f000h    ; if bits 12-15 are cleared, then CPU
  82.         mov     present, 286    ; turn on 80286 flag
  83.         jz    check_fpu    ; if CPU is 80286, check for 80287
  84.  
  85. ;
  86. ;    i386 CPU check
  87. ;    The AC bit, bit #18, is a new bit introduced in the EFLAGS register
  88. ;    on the i486 DX CPU to generate alignment faults.  This bit can be
  89. ;    set on the i486 DX CPU, but not on the i386 CPU.
  90. ;
  91.  
  92.         mov    bx,sp        ; save current stack pointer to align it
  93.         and    sp,not 3    ; align stack to avoid AC fault
  94.         db    66h
  95.         pushf            ; push original EFLAGS
  96.         db    66h
  97.         pop    ax        ; get original EFLAGS
  98.         db    66h
  99.         mov    cx,ax        ; save original EFLAGS
  100.         db    66h        ; xor EAX,40000h
  101.         xor    ax,0        ; flip AC bit in EFLAGS
  102.         dw    4        ; upper 16-bits of xor constant
  103.         db    66h
  104.         push    ax        ; save for EFLAGS
  105.         db    66h
  106.         popf            ; copy to EFLAGS
  107.         db    66h
  108.         pushf            ; push EFLAGS
  109.         db    66h
  110.         pop    ax        ; get new EFLAGS value
  111.         db    66h
  112.         xor    ax,cx        ; if AC bit cannot be changed, is 386
  113.         mov     present, 386    ; turn on i386 flag
  114.         je    check_fpu       ; if CPU is i386, now check for                                 ;    80287/80387 MCP
  115.  
  116. ;
  117. ;    i486 DX CPU / i487 SX MCP and i486 SX CPU checking
  118. ;
  119.         mov     present, 486      ; turn on i486 flag
  120.  
  121. ;
  122. ;    Co-processor checking begins here for the 8086/80286/i386 CPUs.
  123. ;    The algorithm is to determine whether or not the floating-point
  124. ;    status and control words can be written to.  If they are not, no
  125. ;    coprocessor exists.  If the status and control words can be written
  126. ;    to, the correct coprocessor is then determined depending on the
  127. ;    processor id.  Coprocessor checks are first performed for an 8086,
  128. ;    80286 and a i486 DX CPU.  If the coprocessor id is still
  129. ;    undetermined, the system must contain a i386 CPU.  The i386 CPU may
  130. ;    work with either an 80287 or an 80387.  The infinity of the
  131. ;    coprocessor must be checked to determine the correct coprocessor id.
  132. ;
  133.  
  134. check_fpu:                     ; check for 8087/80287/80387
  135.         fninit             ; reset FP status word
  136.         mov     fp_status,5a5ah     ; init temp word to non-zero value
  137.         fnstsw     fp_status     ; save FP status word
  138.         mov    ax,fp_status     ; check FP status word
  139.         cmp     al,0         ; see if correct status with written
  140.         jne     exit         ; jump if not Valid, no NPX installed
  141.  
  142.         fnstcw     fp_status     ; save FP control word
  143.         mov     ax,fp_status     ; check FP control word
  144.         and     ax,103fh      ; see if selected parts looks OK
  145.         cmp     ax,3fh         ; check that 1s & 0s correctly read
  146.         jne     exit     ; jump if not Valid, no NPX installed
  147.  
  148.         cmp    present, 486     ; check if i486 flag is on
  149.         je     is_486         ; if so, jump to set 487
  150.         jmp     not_486         ; else continue with 386 checking
  151.  
  152. is_486:
  153.         mov    FPU, 487
  154.         jmp     exit
  155.  
  156. not_486:
  157.         cmp     present, 386     ; check if i386 flag is on
  158.         jne     print_87_287     ; if i386 flag not on, check NPX for
  159.                      ; 8086/8088/80286
  160. ;
  161. ;   80287/80387 check for the i386 CPU
  162. ;
  163.         fld1             ; use dflt control from FNINIT
  164.         fldz             ; form infinity
  165.         fdiv             ; 8087/80287 says +inf = -inf
  166.         fld    st         ; form negative infinity
  167.         fchs             ; 80387 says +inf <> -inf
  168.         fcompp             ; see if the same and remove them
  169.         fstsw     fp_status     ; look at status from FCOMPP
  170.         mov    ax,fp_status
  171.         mov     FPU, 287
  172.         sahf               ; see if infinities matched
  173.         jz     restore_EFLAGS       ; jump if 8087/80287 is present
  174.         mov     FPU, 387        ; set 80387 mode
  175.  
  176. restore_EFLAGS:
  177.         db    66h
  178.         push    cx           ; push ECX
  179.         db    66h
  180.         popf               ; restore original EFLAGS register
  181.         mov    sp,bx           ; restore original stack pointer
  182.         jmp     exit
  183.  
  184.  
  185. print_87_287:
  186.         cmp     present, 86       ; if 8086/8088 flag is on
  187.         mov     FPU, 87         ; set 8087 mode
  188.         je     exit
  189.         mov     FPU, 287        ; else CPU=80286, store 80287 flag
  190. ;
  191. ; Okay, return values to the calling program:
  192. ;
  193. exit:        mov    ax, present
  194.         mov    bx, FPU
  195.         pop    cx
  196.         pop    ds
  197.         ret
  198. sl_cpuid    endp
  199. ;
  200. StdLib        ends
  201.         end
  202.